#ifndef COMPILE_PRINCIPLE_SYNTAX
#define COMPILE_PRINCIPLE_SYNTAX

#include <iostream>
#include <stack>
#include <functional>
#include <vector>
#include "tool.h"

namespace cp{

const int SymbolCount = 35;
const int NonTermCount = 8;
const int ProdCount = 31;

struct Symbol{
	std::string label;
	int pri;
	bool isTerm;
	Symbol(){}
	Symbol(const char* _label, int _pri, bool _isTerm):
		label(_label), pri(_pri), isTerm(_isTerm){}
	friend std::ostream& operator << (std::ostream& os, const Symbol &sym){
		os << sym.label;
//		os << sym.label << ' ' << sym.pri << ' ' << sym.isTerm;
		return os;
	}
};

extern std::vector<Symbol> symbols;

struct Token{
	int symID, row, col;
	void* cont;
	friend std::ostream& operator << (std::ostream& os, const Token &token){
		os << symbols[token.symID];// << ", row: " << token.row << ", col: " << token.col;
		return os;
	}
};

typedef bool(*Action)();
struct Production{
	int left;
	std::vector<int> right;
	int pri;
	Action action;
	friend bool operator < (const Production &lf, const Production &rt){
		return lf.left != rt.left ? lf.left < rt.left : lf.right < rt.right;
	}
	friend std::ostream& operator << (std::ostream &os, const Production &prod){
		os << symbols[prod.left] << " ->";
		for (auto iter = prod.right.begin(); iter != prod.right.end(); ++iter)
			os << ' ' << symbols[*iter];
		return os;
	}
};

extern std::vector<Production> prods;
extern std::stack<Token*> ts;
extern std::stack<int> ss;
extern void initSymbolAndProds();
extern void initPDA();
extern bool beginParse();
extern int doNextToken(Token* token);
extern void scanNTerms(std::function<void(int)>);
extern void scanTerms(std::function<void(int)>);

}


#endif








